#ifndef CODEGENERATOR_H
#define CODEGENERATOR_H
#include <string>
#include <stdlib.h>
#include <stdio.h>
#include "SymbolTable.h"
#include "Calc.h"
#include "global.h"
using namespace std;
//void writeCode(int);
//void writeCode2(int,int);
//void writeCode3(int,string,int);
//int getNextInstruction();
//int getNextInstruction2();
//void push(string);
//string pop();
//void init();

/*QIF ASSEMBLY CODE */
enum myAssemblyCode{
//	OP					instruction	explaination										space		action
	LOD = 1,	//1		LOD l		Load variable l	to the var and code stack			4 units		var[pc] = name; code[pc] = op; code[pc+1] = addr>>8; code[pc+2] = addr>>16;
	STO,		//2		STO l		Store value to variable l to the var and code stack	4 units		var[pc] = name; code[pc] = op; code[pc+1] = value>>8; code[pc+2] = value>>16;	
	ADD,		//3		ADD			ADDITION
	SUB,		//4		SUB			SUBSTRACTION
	MUL,		//5		MUL			MUTIPLICATION		
	LIT,		//6		LIT l		Load LITERAL(number only) l to the code stack		3 units
	DIVI,		//7		DIVI		Divison
	MODU,		//8		MODU		Module
	WRT,			//9		WRT l		Write variable l to the output stream
	THENb,		//10					
	ELSEc,		//11
	TMT,		//12	END			Terminate the program
	LTR,		//13
	LER,		//14
	EQR,		//15
	NER,		//16
	GTR,		//17
	GER,		//18
	ENDc		//19	ENDc		End of the if-then-else statement

};

const string ASSEMBLYCODE[20] ={
	"","LOD", "STO", "ADD", "SUB", "MUL", "LIT", "DIVI", "MODU","WRT","THENb","ELSEc","TMT",
	"LTR","LER","EQR","NER","GTR","GER","ENDc"
};

/*QIF ASSEMBLY CODE */
//#define LOD 1 // LOD l,a	LOAD VALUE a TO A VARAIBLE l
//#define LD2 2 // LD2 i		LOAD LITERAL from SymbolTable[i]
//#define ADD 3 // ADD		ADDITION
//#define SUB 4//  SUB		SUBSTRACTION
//#define MUL 5//  MUL		MUTIPLICATION
#define MAX_CODE_MEMORY 1024

class CodeGenerator{
private:
	
	char code[MAX_CODE_MEMORY]; // store the opcode and value
	
	string var[MAX_CODE_MEMORY]; // store the variable name
	char stack[MAX_CODE_MEMORY][256]; // the stack in the compiler
	int pc;
	int top;
	int* ebp; // stack back pointer
	int* esp; // stack poiinter
	int next();
	void init();
	SymbolTable* mySymbolTable;
	Calc* myCalculator;
	void MathCalculator(char* var1, char* var2, int op);
	void RelopCalculator(char* var1, char* var2, int op);

public:
	CodeGenerator(SymbolTable*, Calc*);
	void writeCode(int); // OP: WRITE A SINGLE OP TO THE CODE
	void writeCode2(int,int); // op, value : WRITE  the op to the CODE with the value
	void writeCode3(int,char[],int); // op, variable name , address of object
	int getNextInstruction();
	int getNextInstruction2();
	void push(char*);
	char* pop();
	void showCode();
	char* Top();
	static bool isLoadID;
	

};

#endif